home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\WHOIS.C < prev    next >
C/C++ Source or Header  |  1994-12-31  |  28KB  |  1,172 lines

  1. /*
  2.  * whois.c: Some tricky routines for querying the server for information
  3.  * about a nickname using WHOIS.... all the time hiding this from the user.  
  4.  *
  5.  *
  6.  * Written By Michael Sandrof
  7.  *
  8.  * Copyright(c) 1990 
  9.  *
  10.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  11.  */
  12.  
  13. #ifndef lint
  14. static    char    rcsid[] = "@(#)$Id: whois.c,v 1.15 1994/10/09 06:39:35 mrg Stab $";
  15. #endif
  16.  
  17. #undef MONITOR_Q /* this one is for monitoring of the 'whois queue' (debug) */
  18.  
  19. #include "irc.h"
  20.  
  21. #include "whois.h"
  22. #include "hook.h"
  23. #include "lastlog.h"
  24. #include "vars.h"
  25. #include "server.h"
  26. #include "ignore.h"
  27. #include "ircaux.h"
  28. #include "notify.h"
  29. #include "numbers.h"
  30. #include "window.h"
  31. #include "edit.h"
  32. #include "output.h"
  33. #include "parse.h"
  34. #include "ctcp.h"
  35.  
  36. char    whois_nick[] = "#WHOIS#";
  37. char    wait_nick[] = "#WAIT#";
  38. char    redirect_nick[] = "#RED#";
  39.  
  40. /* current setting for BEEP_ON_MSG */
  41. int    beep_on_level;
  42.  
  43. static    int    ignore_whois_crap = 0;
  44. static    int    eat_away = 0;
  45. /*
  46. static    WhoisStuff whois_stuff =
  47. {
  48.     (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0,
  49.     (char *) 0, (char *) 0, (char *) 0, (char *) 0, 0, 0, 0
  50. };
  51. */
  52.  
  53. /* WQ_head and WQ_tail point to the head and tail of the whois queue */
  54. WhoisQueue *WQ_head = (WhoisQueue *) 0;
  55. WhoisQueue *WQ_tail = (WhoisQueue *) 0;
  56.  
  57. static    char    show_away_flag = 0;
  58.  
  59. extern    void    typed_add_to_whois_queue();
  60. extern    void    ison_notify();
  61.  
  62. void    set_beep_on_msg(str)
  63. char    *str;
  64. {
  65.     beep_on_level = parse_lastlog_level(str);
  66.     set_string_var(BEEP_ON_MSG_VAR, bits_to_lastlog_level(beep_on_level));
  67. }
  68.  
  69. /*
  70.  * whois_queue_head: returns the nickname at the head of the whois queue, or
  71.  * NULL if the queue is empty.  It does not modify the queue in any way. 
  72.  */
  73. char    *whois_queue_head()
  74. {
  75.     if ((WQ_head = (WhoisQueue *) get_server_qhead(from_server)) != NULL)
  76.         return (WQ_head->nick);
  77.     else
  78.         return ((char *) 0);
  79. }
  80.  
  81. int    whois_type_head()
  82. {
  83.     if ((WQ_head = (WhoisQueue *) get_server_qhead(from_server)) != NULL)
  84.         return (WQ_head->type);
  85.     else
  86.         return -1;
  87. }
  88.  
  89. void    (*whois_func_head())()
  90. {
  91.     if ((WQ_head=(WhoisQueue *) get_server_qhead(from_server)) != NULL)
  92.         return (WQ_head->func);
  93.     else
  94.         return NULL;
  95. }
  96.  
  97. /*
  98.  * remove_from_whois_queue: removes the top element of the whois queue and
  99.  * returns the element as its function value.  This routine repairs handles
  100.  * all queue stuff, but the returned element is mallocd and must be freed by
  101.  * the calling routine 
  102.  */
  103. static    WhoisQueue *remove_from_whois_queue()
  104. {
  105.     WhoisQueue *new;
  106.  
  107.     new = (WhoisQueue *) get_server_qhead(from_server);
  108.     set_server_qhead(from_server, new->next);
  109.     if (new->next == (WhoisQueue *) 0)
  110.         set_server_qtail(from_server, (WhoisQueue *) 0);
  111.     return (new);
  112. }
  113.  
  114. /*
  115.  * clean_whois_queue: this empties out the whois queue.  This is used after
  116.  * server reconnection to assure that no bogus entries are left in the whois
  117.  * queue 
  118.  */
  119. void    clean_whois_queue()
  120. {
  121.     WhoisQueue *thing;
  122.  
  123.     while (whois_queue_head())
  124.     {
  125.         thing = remove_from_whois_queue();
  126.         new_free(&thing->nick);
  127.         new_free(&thing->text);
  128.         new_free(&thing);
  129.     }
  130.     ignore_whois_crap = 0;
  131.     eat_away = 0;
  132. }
  133. /* ison_returned: this is called when numeric 303 is received in
  134.  * numbers.c. ISON must always be the property of the WHOIS queue.
  135.  * Although we will check first that the top element expected is
  136.  * actually an ISON.
  137.  */
  138. /*ARGSUSED*/
  139. void    ison_returned(from, ArgList)
  140. char    *from,
  141.     **ArgList;
  142. {
  143.     WhoisQueue *thing;
  144.  
  145.     if (whois_type_head() == WHOIS_ISON)
  146.     {
  147.         thing = remove_from_whois_queue();
  148.         thing->func(thing->nick, ArgList[0]? ArgList[0] : empty_string);
  149.         new_free(&thing->nick);
  150.         new_free(&thing->text);
  151.         new_free(&thing);
  152.     }
  153.     else
  154.         ison_ison(NULL, ArgList[0] ? ArgList[0] : empty_string);
  155. }
  156.  
  157. /* userhost_returned: this is called when numeric 302 is received in
  158.  * numbers.c. USERHOST must also remain the property of the WHOIS
  159.  * queue. Sending it without going via the WHOIS queue will cause
  160.  * the queue to become corrupted.
  161.  *
  162.  * While USERHOST gives us similar information to WHOIS, this routine's
  163.  * format is a little different to those that handle the WHOIS numerics.
  164.  * A list of nicks can be supplied to USERHOST, and any of those
  165.  * nicks are not currently signed on, it will just omit reporting it.
  166.  * this means we must go through the list of nicks returned and check
  167.  * them for missing entries. This means stepping through the requested
  168.  * nicks one at a time.
  169.  *
  170.  * A side effect of this is that user initiated USERHOST requests get
  171.  * reported as separate replies even though one request gets made and
  172.  * only one reply is actually received. This should make it easier for
  173.  * people wanting to use USERHOST for their own purposes.
  174.  *
  175.  * In this routine, cnick points to all the information in the next
  176.  * entry from the returned data.
  177.  */
  178. /*ARGSUSED*/
  179. void    userhost_returned(from, ArgList)
  180. char    *from,
  181.     **ArgList;
  182. {
  183.     WhoisQueue *thing;
  184.     WhoisStuff *whois_stuff = NULL;
  185.     char    *nick,
  186.         *cnick = NULL,
  187.         *tnick;
  188.     char    *user,
  189.         *cuser = (char *) 0;
  190.     char    *host,
  191.         *chost = (char *) 0;
  192.     int    ishere,
  193.         cishere = 1;
  194.     int    isoper,
  195.         cisoper = 0;
  196.     int    noton,
  197.         isuser,
  198.         parsed;
  199.     char    *queue_nicks;
  200.  
  201.     if (!ArgList[0])
  202.         return;
  203.     if (whois_type_head() == WHOIS_USERHOST)
  204.     {
  205.         isuser = (whois_func_head() == USERHOST_USERHOST);
  206.         whois_stuff = get_server_whois_stuff(from_server);
  207.         thing = remove_from_whois_queue();
  208.         queue_nicks = thing->nick;
  209.     }
  210.     else
  211.     {
  212.         isuser = 1;
  213.         thing = (WhoisQueue *) 0;
  214.         queue_nicks = (char *) 0;
  215.         whois_stuff = NULL;
  216.     }
  217.     parsed = 0;
  218.     while ((parsed || (cnick = next_arg(ArgList[0], ArgList))) ||
  219.             queue_nicks)
  220.     {
  221.         if (queue_nicks)
  222.         {
  223.             tnick = next_arg(queue_nicks, &queue_nicks);
  224.             if (!*queue_nicks)
  225.                 queue_nicks = (char *) 0;
  226.         }
  227.         else
  228.             tnick = NULL;
  229.         if (cnick && !parsed)
  230.         {
  231.             if (!(cuser = index(cnick,'=')))
  232.                 break;
  233.             if (*(cuser - 1) == '*')
  234.             {
  235.                 *(cuser - 1) = '\0';
  236.                 cisoper = 1;
  237.             }
  238.             else
  239.                 cisoper = 0;
  240.             *cuser++ = '\0';
  241.             if (*cuser++ == '+')
  242.                 cishere = 1;
  243.             else
  244.                 cishere = 0;
  245.             if (!(chost = index(cuser, '@')))
  246.                 break;
  247.             *chost++ = '\0';
  248.             parsed = 1;
  249.         }
  250.         if (!cnick || (tnick && my_stricmp(cnick, tnick)))
  251.         {
  252.             if (tnick)
  253.                 nick = tnick;
  254.             else
  255.                 nick = cnick;
  256.             user = host = "<UNKNOWN>";
  257.             isoper = 0;
  258.             ishere = 1;
  259.             noton = 1;
  260.         }
  261.         else
  262.         {
  263.             nick = cnick;
  264.             user = cuser;
  265.             host = chost;
  266.             isoper = cisoper;
  267.             ishere = cishere;
  268.             noton = parsed = 0;
  269.         }
  270.         if (!isuser)
  271.         {
  272.             malloc_strcpy(&whois_stuff->nick, nick);
  273.             malloc_strcpy(&whois_stuff->user, user);
  274.             malloc_strcpy(&whois_stuff->host, host);
  275.             whois_stuff->oper = isoper;
  276.             whois_stuff->not_on = noton;
  277.             if (!ishere)
  278.                 malloc_strcpy(&whois_stuff->away, empty_string);
  279.             else
  280.                 new_free(&whois_stuff->away);
  281.             thing->func(whois_stuff, tnick, thing->text);
  282.             new_free(&whois_stuff->away);
  283.         }
  284.         else
  285.         {
  286.             if (do_hook(current_numeric, "%s %s %s %s %s", nick,
  287.                 isoper ? "+" : "-", ishere ? "+" : "-", user, host))
  288.                 put_it("%s %s is %s@%s%s%s", numeric_banner(),
  289.                     nick, user, host, isoper ?
  290.                     " (Is an IRC operator)" : empty_string,
  291.                     ishere ? empty_string : " (away)");
  292.         }
  293.     }
  294.     if (thing)
  295.     {
  296.         new_free(&thing->nick);
  297.         new_free(&thing->text);
  298.         new_free(&thing);
  299.     }
  300. }
  301.  
  302. /*
  303.  * whois_name: routine that is called when numeric 311 is received in
  304.  * numbers.c. This routine parses out the information in the numeric and
  305.  * saves it until needed (see whois_server()).  If the whois queue is empty,
  306.  * this routine simply displays the data in the normal fashion.  Why would
  307.  * the queue ever be empty, you ask? If the user does a "WHOIS *" or any
  308.  * other whois with a wildcard, you will get multiple returns from the
  309.  * server.  So, instead of attempting to handle each of these, only the first
  310.  * is handled, and the others fall through.  It is up to the programmer to
  311.  * prevent wildcards from interfering with what they want done.  See
  312.  * channel() in edit.c 
  313.  */
  314. void    whois_name(from, ArgList)
  315. char    *from;
  316. char    **ArgList;
  317. {
  318.     char    *nick,
  319.         *user,
  320.         *host,
  321.         *channel,
  322.         *ptr,
  323.         *name;
  324.     WhoisStuff *whois_stuff;
  325.  
  326.     PasteArgs(ArgList, 4);
  327.     nick = ArgList[0];
  328.     user = ArgList[1];
  329.     host = ArgList[2];
  330.     channel = ArgList[3];
  331.     name = ArgList[4];
  332.     if (!nick || !user || !host || !channel || !name)
  333.         return;
  334.     whois_stuff = get_server_whois_stuff(from_server);
  335.     if ((ptr = whois_queue_head()) &&
  336.         (whois_type_head() == WHOIS_WHOIS) &&
  337.         (my_stricmp(ptr, nick) == 0))
  338.     {
  339.         malloc_strcpy(&whois_stuff->nick, nick);
  340.         malloc_strcpy(&whois_stuff->user, user);
  341.         malloc_strcpy(&whois_stuff->host, host);
  342.         malloc_strcpy(&whois_stuff->name, name);
  343.         malloc_strcpy(&whois_stuff->channel, channel);
  344.         new_free(&whois_stuff->away);
  345.         whois_stuff->oper = 0;
  346.         whois_stuff->chop = 0;
  347.         whois_stuff->not_on = 0;
  348.         ignore_whois_crap = 1;
  349.         eat_away = 1;
  350.     }
  351.     else
  352.     {
  353.         ignore_whois_crap = 0;
  354.         eat_away = 0;
  355.         message_from((char *) 0, LOG_CRAP);
  356.         if (do_hook(current_numeric, "%s %s %s %s %s %s", from, nick,
  357.                 user, host, channel, name))
  358.             put_it("%s %s is %s@%s (%s)", numeric_banner(), nick,
  359.                     user, host, name);
  360.     }
  361. }
  362.  
  363. /*
  364.  * whowas_name: same as whois_name() above but it is called with a numeric of
  365.  * 314 when the user does a WHOWAS or when a WHOIS'd user is no longer on IRC 
  366.  * and has set the AUTO_WHOWAS variable.
  367.  */
  368. void    whowas_name(from, ArgList)
  369. char    *from;
  370. char    **ArgList;
  371. {
  372.     char    *nick,
  373.         *user,
  374.         *host,
  375.         *channel,
  376.         *ptr,
  377.         *name;
  378.     WhoisStuff *whois_stuff;
  379.     int    lastlog_level;
  380.  
  381.     PasteArgs(ArgList, 4);
  382.     nick = ArgList[0];
  383.     user = ArgList[1];
  384.     host = ArgList[2];
  385.     channel = ArgList[3];
  386.     name = ArgList[4];
  387.     if (!nick || !user || !host || !channel || !name)
  388.         return;
  389.  
  390.     lastlog_level = set_lastlog_msg_level(LOG_CRAP);
  391.     whois_stuff = get_server_whois_stuff(from_server);
  392.     if ((ptr = whois_queue_head()) &&
  393.         (whois_type_head == WHOIS_WHOIS) &&
  394.         (my_stricmp(ptr, nick) == 0))
  395.     {
  396.         malloc_strcpy(&whois_stuff->nick, nick);
  397.         malloc_strcpy(&whois_stuff->user, user);
  398.         malloc_strcpy(&whois_stuff->host, host);
  399.         malloc_strcpy(&whois_stuff->name, name);
  400.         malloc_strcpy(&whois_stuff->channel, channel);
  401.         new_free(&whois_stuff->away);
  402.         whois_stuff->oper = 0;
  403.         whois_stuff->chop = 0;
  404.         whois_stuff->not_on = 1;
  405.         ignore_whois_crap = 1;
  406.     }
  407.     else
  408.     {
  409.         ignore_whois_crap = 0;
  410.         if (do_hook(current_numeric, "%s %s %s %s %s %s", from, nick,
  411.                 user, host, channel, name))
  412.             put_it("%s %s was %s@%s (%s) on channel %s",
  413.                 numeric_banner(), nick, user, host, name,
  414.                 (*channel == '*') ? "*private*" : channel);
  415.     }
  416.     set_lastlog_msg_level(lastlog_level);
  417. }
  418.  
  419. void    whois_channels(from, ArgList)
  420. char    *from;
  421. char    **ArgList;
  422. {
  423.     char    *ptr;
  424.     char    *line;
  425.     WhoisStuff *whois_stuff;
  426.  
  427.     PasteArgs(ArgList, 1);
  428.     line = ArgList[1];
  429.     whois_stuff = get_server_whois_stuff(from_server);
  430.     if ((ptr = whois_queue_head()) &&
  431.         (whois_type_head() == WHOIS_WHOIS) &&
  432.         whois_stuff->nick &&
  433.         (my_stricmp(ptr, whois_stuff->nick) == 0))
  434.     {
  435.         if (whois_stuff->channels == (char *) 0)
  436.             malloc_strcpy(&whois_stuff->channels, line);
  437.         else
  438.             malloc_strcat(&whois_stuff->channels, line);
  439.     }
  440.     else
  441.     {
  442.         if (do_hook(current_numeric, "%s %s", from, line))
  443.             put_it("%s on channels: %s", numeric_banner(), line);
  444.     }
  445. }
  446.  
  447. /*
  448.  * whois_server: Called in numbers.c when a numeric of 312 is received.  If
  449.  * all went well, this routine collects the needed information, pops the top
  450.  * element off the queue and calls the function as described above in
  451.  * WhoisQueue.  It then releases all the mallocd data.  If the queue is empty
  452.  * (same case as described in whois_name() above), the information is simply
  453.  * displayed in the normal fashion. Added a check to see if whois_stuff->nick
  454.  * is NULL. This can happen if something is added to an empty whois queue
  455.  * between the whois name being received and the server.
  456.  */
  457. void    whois_server(from, ArgList)
  458. char    *from;
  459. char    **ArgList;
  460. {
  461.     char    *server,
  462.         *ptr;
  463.     char    *line;
  464.     WhoisStuff *whois_stuff;
  465.  
  466.     show_away_flag = 1;
  467.     if (!ArgList[0] || !ArgList[1])
  468.         return;
  469.     if (ArgList[2])
  470.     {
  471.         server = ArgList[1];
  472.         line = ArgList[2];
  473.     }
  474.     else
  475.     {
  476.         server = ArgList[0];
  477.         line = ArgList[1];
  478.     }
  479.     whois_stuff = get_server_whois_stuff(from_server);
  480.     if ((ptr = whois_queue_head()) &&
  481.         (whois_type_head() == WHOIS_WHOIS) &&
  482.         whois_stuff->nick && /* This is *weird* */
  483.     (my_stricmp(ptr, whois_stuff->nick) == 0))
  484.     {
  485.         malloc_strcpy(&whois_stuff->server, server);
  486.         malloc_strcpy(&whois_stuff->server_stuff, line);
  487.     }
  488.     else
  489.     {
  490.         if (do_hook(current_numeric, "%s %s %s", from, server, line))
  491.             put_it("%s on irc via server %s (%s)",
  492.                 numeric_banner(), server, line);
  493.     }
  494. }
  495.  
  496. /*
  497.  * whois_oper: This displays the operator status of a user, as returned by
  498.  * numeric 313 from the server.  If the ignore_whois_crap flag is set,
  499.  * nothing is dispayed. 
  500.  */
  501. void    whois_oper(from, ArgList)
  502. char    *from;
  503. char    **ArgList;
  504. {
  505.     WhoisStuff *whois_stuff;
  506.  
  507.     whois_stuff = get_server_whois_stuff(from_server);
  508.     PasteArgs(ArgList, 1);
  509.     if (ignore_whois_crap)
  510.         whois_stuff->oper = 1;
  511.     else
  512.     {
  513.         char    *nick;
  514.  
  515.         if ((nick = ArgList[0]) != NULL)
  516.         {
  517.             if (do_hook(current_numeric, "%s %s %s", from, nick,
  518.                     ArgList[1]))
  519.                 put_it("%s %s %s%s", numeric_banner(), nick,
  520.                     ArgList[1], (server_list[from_server].version >
  521.                     Server2_7) ? empty_string
  522.                            : " (is an IRC operator)");
  523.         }
  524.     }
  525. }
  526.  
  527. void    whois_lastcom(from, ArgList)
  528. char    *from;
  529. char    **ArgList;
  530. {
  531.     if (!ignore_whois_crap)
  532.     {
  533.         char    flag, *nick, *idle_str;
  534.         int    idle;
  535.  
  536.         PasteArgs(ArgList, 2);
  537.         if ((nick = ArgList[0]) && (idle_str = ArgList[1]) &&
  538.                 do_hook(current_numeric, "%s %s %s %s", from,
  539.                     nick, idle_str, ArgList[2]))
  540.         {
  541.             if ((idle = atoi(idle_str)) > 59)
  542.             {
  543.                 idle = idle/60;
  544.                 flag = 1;
  545.             }
  546.             else
  547.                 flag = 0;
  548.             put_it("%s %s has been idle %d %ss", numeric_banner(),
  549.                 nick, idle, flag? "minute": "second");
  550.         }
  551.     }
  552. }
  553.  
  554. /*
  555.  * whois_chop: This displays the operator status of a user, as returned by
  556.  * numeric 313 from the server.  If the ignore_whois_crap flag is set,
  557.  * nothing is dispayed. 
  558.  */
  559. void    whois_chop(from, ArgList)
  560. char    *from;
  561. char    **ArgList;
  562. {
  563.     WhoisStuff *whois_stuff;
  564.  
  565.     whois_stuff = get_server_whois_stuff(from_server);
  566.     PasteArgs(ArgList, 1);
  567.     if (ignore_whois_crap)
  568.         whois_stuff->chop = 1;
  569.     else
  570.     {
  571.         char    *nick;
  572.  
  573.         if ((nick = ArgList[0]) != NULL)
  574.         {
  575.             if (do_hook(current_numeric, "%s %s %s",from, nick,
  576.                     ArgList[1]))
  577.                 put_it("%s %s (is a channel operator)",
  578.                     numeric_banner(), nick, ArgList[1]);
  579.         }
  580.     }
  581. }
  582.  
  583. void    end_of_whois(from, ArgList)
  584. char    *from;
  585. char    **ArgList;
  586. {
  587.     char    *nick;
  588.     char    *ptr;
  589.     WhoisStuff *whois_stuff;
  590.  
  591.     whois_stuff = get_server_whois_stuff(from_server);
  592.  
  593.     show_away_flag = 0;
  594.     set_server_whois(from_server,1);
  595.     if ((nick = ArgList[0]) != NULL)
  596.     {
  597.         ptr = whois_queue_head();
  598.         if (ptr && (whois_type_head() == WHOIS_WHOIS) &&
  599.             (my_stricmp(ptr, nick) == 0))
  600.         {
  601.             WhoisQueue *thing;
  602.  
  603.             thing = remove_from_whois_queue();
  604.             whois_stuff->not_on = 0;
  605.             thing->func(whois_stuff, thing->nick, thing->text);
  606.             new_free(&whois_stuff->channels);
  607.             new_free(&thing->nick);
  608.             new_free(&thing->text);
  609.             new_free(&thing);
  610.             ignore_whois_crap = 0;
  611.             return;
  612.         }
  613.         PasteArgs(ArgList, 0);
  614.         if (do_hook(current_numeric, "%s %s", from, ArgList[0]))
  615.             if (get_int_var(SHOW_END_OF_MSGS_VAR))
  616.                 display_msg(from, ArgList);
  617.     }
  618. }
  619.  
  620. /*
  621.  * no_such_nickname: Handler for numeric 401, the no such nickname error. If
  622.  * the nickname given is at the head of the queue, then this routine pops the
  623.  * top element from the queue, sets the whois_stuff->flag to indicate that the
  624.  * user is no longer on irc, then calls the func() as normal.  It is up to
  625.  * that function to set the ignore_whois_crap variable which will determine
  626.  * if any other information is displayed or not. 
  627.  *
  628.  * that is, it used to.  now it does bugger all, seeing all the functions that
  629.  * used to use it, now use no such command.  -phone, april 1993.
  630.  */
  631. /*ARGSUSED*/
  632. void    no_such_nickname(from, ArgList)
  633. char    *from,
  634.     **ArgList;
  635. {
  636.     char    *nick;
  637.  
  638.     PasteArgs(ArgList, 1);
  639.     nick = ArgList[0];
  640.     if (do_hook(current_numeric, "%s %s %s", from, nick, ArgList[1]))
  641.         put_it("%s %s: %s", numeric_banner(), nick, ArgList[1]);
  642.     notify_mark(nick, 0, 0);
  643.     if ((get_server_version(from_server) > Server2_5) &&
  644.         get_int_var(AUTO_WHOWAS_VAR))
  645.         send_to_server("WHOWAS %s", nick);
  646. }
  647.  
  648. /*
  649.  * user_is_away: called when a 301 numeric is received.  Nothing is displayed
  650.  * by this routine if the ignore_whois_crap flag is set 
  651.  */
  652. /*ARGSUSED*/
  653. void    user_is_away(from, ArgList)
  654. char    *from,
  655.     **ArgList;
  656. {
  657.     static    char    *last_away_msg = (char *) 0,
  658.             *last_away_nick = (char *) 0;
  659.     char    *message,
  660.         *who;
  661.     WhoisStuff *whois_stuff;
  662.  
  663. if (!from)
  664.     return;
  665.  
  666.     PasteArgs(ArgList, 1);
  667.     whois_stuff = get_server_whois_stuff(from_server);
  668.  
  669.     if ((who = ArgList[0]) && (message = ArgList[1]))
  670.     {
  671.         if (whois_stuff->nick && (!strcmp(who, whois_stuff->nick)) &&
  672.                 eat_away)
  673.             malloc_strcpy(&whois_stuff->away, message);
  674.         else
  675.         {
  676.             if (!show_away_flag && get_int_var(SHOW_AWAY_ONCE_VAR))
  677.             {
  678.                 if (!last_away_msg || strcmp(last_away_nick,
  679.                     from) || strcmp(last_away_msg, message))
  680.                 {
  681.                     malloc_strcpy(&last_away_nick, from);
  682.                     malloc_strcpy(&last_away_msg, message);
  683.                 }
  684.                 else return;
  685.             }
  686.             if (do_hook(current_numeric, "%s %s", who, message))
  687.                 put_it("%s %s is away: %s",numeric_banner(),
  688.                     who, message);
  689.         }
  690.         eat_away = 0;
  691.     }
  692. }
  693.  
  694. /*
  695.  * The stuff below this point are all routines suitable for use in the
  696.  * add_to_whois_queue() call as the func parameter 
  697.  */
  698.  
  699. /*
  700.  * whois_ignore_msgs: This is used when you are ignoring MSGs using the
  701.  * user@hostname format 
  702.  */
  703. void    whois_ignore_msgs(stuff, nick, text)
  704. WhoisStuff *stuff;
  705. char    *nick;
  706. char    *text;
  707. {
  708.     char    *ptr;
  709.     int    level;
  710.  
  711.     if (stuff)
  712.     {
  713.         ptr = (char *) new_malloc(strlen(stuff->user) +
  714.             strlen(stuff->host) + 2);
  715.         strcpy(ptr, stuff->user);
  716.         strcat(ptr, "@");
  717.         strcat(ptr, stuff->host);
  718.         if (is_ignored(ptr, IGNORE_MSGS) != IGNORED)
  719.         {
  720.             level = set_lastlog_msg_level(LOG_MSG);
  721.             message_from(stuff->nick, LOG_MSG);
  722.         if (sed == 1 && !do_hook(ENCRYPTED_PRIVMSG_LIST,"%s %s", stuff->nick,text))
  723.             {
  724.             sed = 0;
  725.                 return;
  726.             }
  727.             if (do_hook(MSG_LIST, "%s %s", stuff->nick, text))
  728.             {
  729.                 if (away_set)
  730.                 {
  731.                     time_t    t;
  732.                     char    *msg = (char *) 0;
  733.  
  734.                     t = time(0);
  735.                     msg = (char *) new_malloc(strlen(text)
  736.                         + 20);
  737.                     sprintf(msg, "%s <%.16s>", text,
  738.                         ctime(&t));
  739.                     put_it("*%s* %s", stuff->nick, msg);
  740.                     new_free(&msg);
  741.                     beep_em(get_int_var(BEEP_WHEN_AWAY_VAR));
  742.                 }
  743.                 else
  744.                 {
  745.                     put_it("*%s* %s", stuff->nick, text);
  746.                     beep_em(get_int_var(BEEP_ON_MSG_VAR));
  747.                 }
  748.             }
  749.             if (beep_on_level & LOG_MSG)
  750.                 beep_em(1);
  751.             set_lastlog_msg_level(level);
  752.             sed = 0;
  753.             notify_mark(nick, 1, 0);
  754.         }
  755.         else
  756.             send_to_server("NOTICE %s :%s is ignoring you.",
  757.                 nick, get_server_nickname(from_server));
  758.         new_free(&ptr);
  759.     }
  760. }
  761.  
  762. /*ARGSUSED*/
  763. void    whois_nickname(stuff,nick,text)
  764. WhoisStuff *stuff;
  765. char    *nick;
  766. char    *text;
  767. {
  768.     if (stuff)
  769.     {
  770.         if (!(my_stricmp(stuff->user,username)) &&
  771.                 (!my_stricmp(stuff->host,hostname)))
  772.             set_server_nickname(from_server,nick);
  773.     }
  774. }
  775.  
  776. /*
  777.  * whois_ignore_notices: This is used when you are ignoring NOTICEs using the
  778.  * user@hostname format 
  779.  */
  780. /*ARGSUSED*/
  781. void    whois_ignore_notices(stuff, nick, text)
  782. WhoisStuff *stuff;
  783. char    *nick;
  784. char    *text;
  785. {
  786.     char    *ptr;
  787.     int    level;
  788.  
  789.     if (stuff)
  790.     {
  791.         ptr = (char *) new_malloc(strlen(stuff->user) +
  792.             strlen(stuff->host) + 2);
  793.         strcpy(ptr, stuff->user);
  794.         strcat(ptr, "@");
  795.         strcat(ptr, stuff->host);
  796.         if (is_ignored(ptr, IGNORE_NOTICES) != IGNORED)
  797.         {
  798.             level = set_lastlog_msg_level(LOG_NOTICE);
  799.             message_from(stuff->nick, LOG_NOTICE);
  800.             if (sed == 0 && !do_hook(ENCRYPTED_NOTICE_LIST,"%s %s", stuff->nick, text))
  801.             {
  802.                 sed = 0;
  803.                 return;
  804.             }
  805.             if (do_hook(NOTICE_LIST, "%s %s", stuff->nick, text))
  806.                 put_it("-%s- %s", stuff->nick, text);
  807.             set_lastlog_msg_level(level);
  808.             sed = 0;
  809.         }
  810.         new_free(&ptr);
  811.     }
  812. }
  813.  
  814. /*
  815.  * whois_ignore_invites: This is used when you are ignoring INVITES using the
  816.  * user@hostname format 
  817.  */
  818. void    whois_ignore_invites(stuff, nick, text)
  819. WhoisStuff *stuff;
  820. char    *nick;
  821. char    *text;
  822. {
  823.     char    *ptr;
  824.  
  825.     if (stuff)
  826.     {
  827.         ptr = (char *) new_malloc(strlen(stuff->user) +
  828.             strlen(stuff->host) + 2);
  829.         strcpy(ptr, stuff->user);
  830.         strcat(ptr, "@");
  831.         strcat(ptr, stuff->host);
  832.         if (is_ignored(ptr, IGNORE_INVITES) != IGNORED)
  833.         {
  834.             if (do_hook(INVITE_LIST, "%s %s", stuff->nick, text))
  835.                 say("%s invites you to channel %s",
  836.                     stuff->nick, text);
  837.             malloc_strcpy(&invite_channel, text);
  838.         }
  839.         else
  840.             send_to_server("NOTICE %s :%s is ignoring you.",
  841.                 nick, get_server_nickname(from_server));
  842.         new_free(&ptr);
  843.     }
  844. }
  845.  
  846. /*
  847.  * whois_ignore_walls: This is used when you are ignoring WALLS using the
  848.  * user@hostname format 
  849.  */
  850. /*ARGSUSED*/
  851. void    whois_ignore_walls(stuff, nick, text)
  852. WhoisStuff *stuff;
  853. char    *nick;
  854. char    *text;
  855. {
  856.     char    *ptr;
  857.     int    level;
  858.  
  859.     level = set_lastlog_msg_level(LOG_WALL);
  860.     message_from(stuff->nick, LOG_WALL);
  861.     if (stuff)
  862.     {
  863.         ptr = (char *) new_malloc(strlen(stuff->user) +
  864.             strlen(stuff->host) + 2);
  865.         strcpy(ptr, stuff->user);
  866.         strcat(ptr, "@");
  867.         strcat(ptr, stuff->host);
  868.         if (is_ignored(ptr, IGNORE_WALLS) != IGNORED)
  869.         {
  870.             if (do_hook(WALL_LIST, "%s %s", stuff->nick, text))
  871.                 put_it("#%s# %s", stuff->nick, text);
  872.             if (beep_on_level & LOG_WALL)
  873.                 beep_em(1);
  874.         }
  875.         new_free(&ptr);
  876.     }
  877.     set_lastlog_msg_level(level);
  878. }
  879.  
  880. void    convert_to_whois()
  881. {
  882.     char    *NextAsked;
  883.     char    *Names;
  884.     WhoisQueue *thing;
  885.     void    (*func)();
  886.  
  887.     if (whois_type_head() != WHOIS_USERHOST ||
  888.         whois_type_head() != WHOIS_WHOIS)
  889.     {
  890.         say("Server does not support USERHOST");
  891.         return; /* USERHOST sent interactively. */
  892.     }
  893.     thing = remove_from_whois_queue();
  894.     switch(thing->type)
  895.     {
  896.     case WHOIS_ISON:
  897.         Names = thing->nick;
  898.         for (; (NextAsked = next_arg(Names, &Names));)
  899.         {
  900.             if (thing->func == ison_notify)
  901.             {
  902.                 func= (void (*)())whois_notify;
  903.                 add_to_whois_queue(NextAsked, func, "%s",
  904.                     NextAsked);
  905.             }
  906.             else
  907.                 say("Server does not support ISON");
  908.         }
  909.         break;
  910.     case WHOIS_USERHOST:
  911.         add_to_whois_queue(thing->nick, thing->func, "%s", thing->text);
  912.         break;
  913.     }
  914.     new_free(&thing->nick);
  915.     new_free(&thing->text);
  916.     new_free(&thing);
  917. }
  918.  
  919. void    ison_notify(AskedFor, AreOn)
  920. char    *AskedFor;
  921. char    *AreOn;
  922. {
  923.     char    *NextAsked;
  924.     char    *NextGot;
  925.  
  926.     NextGot = next_arg(AreOn, &AreOn);
  927.     while ((NextAsked = next_arg(AskedFor, &AskedFor)) != NULL)
  928.     {
  929.         if (NextGot && !my_stricmp(NextAsked, NextGot))
  930.         {
  931.             notify_mark(NextAsked, 1, 1);
  932.             NextGot = next_arg(AreOn, &AreOn);
  933.         }
  934.         else
  935.             notify_mark(NextAsked, 0, 1);
  936.     }
  937. }
  938.  
  939. /*
  940.  * whois_notify: used by the routines in notify.c to tell when someone has
  941.  * signed on or off irc 
  942.  */
  943. /*ARGSUSED*/
  944. void    whois_notify(stuff, nick, text)
  945. WhoisStuff *stuff;
  946. char    *nick;
  947. char    *text;
  948. {
  949.     int    level;
  950.  
  951.     level = set_lastlog_msg_level(LOG_CRAP);
  952.     if (stuff)
  953.         notify_mark(stuff->nick, 1, 1);
  954.     else
  955.         notify_mark(nick, 0, 1);
  956.     set_lastlog_msg_level(level);
  957. }
  958.  
  959. void    whois_new_wallops(stuff, nick, text)
  960. WhoisStuff *stuff;
  961. char    *nick;
  962. char    *text;
  963. {
  964.     int    flag,
  965.     level;
  966.     char    *high;
  967.  
  968.     flag = is_ignored(nick, IGNORE_WALLOPS);
  969.     if (flag != IGNORED)
  970.     {
  971.         if (flag == HIGHLIGHTED)
  972.             high = &highlight_char;
  973.         else
  974.             high = empty_string;
  975.         if (stuff && (ignore_usernames & IGNORE_WALLOPS))
  976.         {
  977.             char    *ptr;
  978.  
  979.             ptr = (char *) new_malloc(strlen(stuff->user) +
  980.                 strlen(stuff->host) + 2);
  981.             strcpy(ptr, stuff->user);
  982.             strcat(ptr, "@");
  983.             strcat(ptr, stuff->host);
  984.             if (is_ignored(ptr, IGNORE_WALLOPS) == IGNORED)
  985.             {
  986.                 new_free(&ptr);
  987.                 return;
  988.             }
  989.             new_free(&ptr);
  990.         }
  991.         message_from(nick, LOG_WALLOP);
  992.         level = set_lastlog_msg_level(LOG_WALLOP);
  993.         if (stuff)
  994.         {
  995.             if (do_hook(WALLOP_LIST, "%s %s %s", nick,
  996.                     (stuff->oper ? "+" : "-"), text))
  997.                 put_it("%s!%s%s!%s %s", high, nick,
  998.                     stuff->oper ? "*" : empty_string,
  999.                     high, text);
  1000.         }
  1001.         else
  1002.         {
  1003.             if (do_hook(WALLOP_LIST, "%s - %s", nick, text))
  1004.                 put_it("%s!%s!%s %s", high, nick, high, text);
  1005.         }
  1006.         if (beep_on_level & LOG_WALLOP)
  1007.             beep_em(1);
  1008.         set_lastlog_msg_level(level);
  1009.     }
  1010. }
  1011.  
  1012. /* I put the next routine down here to keep my compile quiet */
  1013.  
  1014. /*
  1015.  * add_to_whois_queue: This routine is called whenever you want to do a WHOIS
  1016.  * or WHOWAS.  What happens is this... each time this function is called it
  1017.  * adds a new element to the whois queue using the nick and func as in
  1018.  * WhoisQueue, and creating the text element using the format and args.  It
  1019.  * then issues the WHOIS or WHOWAS.  
  1020.  */
  1021. #ifdef USE_STDARG_H
  1022. void    add_to_whois_queue(char *nick, void (*func)(), char *format, ...)
  1023. #else
  1024. void    add_to_whois_queue(nick, func, format, arg1, arg2,
  1025.         arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
  1026. void    (*func) ();
  1027. char    *format,
  1028.     *nick;
  1029. char    *arg1,
  1030.     *arg2,
  1031.     *arg3,
  1032.     *arg4,
  1033.     *arg5,
  1034.     *arg6,
  1035.     *arg7,
  1036.     *arg8,
  1037.     *arg9,
  1038.     *arg10;
  1039. #endif
  1040. {
  1041.     int    Type;
  1042. #ifdef USE_STDARG_H
  1043.     va_list    vlist;
  1044.  
  1045.     va_start(vlist, format);
  1046. #endif
  1047.  
  1048.     if (func == USERHOST_USERHOST || func == userhost_cmd_returned)
  1049.         Type = WHOIS_USERHOST;
  1050.     else
  1051.         Type = WHOIS_WHOIS;
  1052. #ifdef USE_STDARG_H
  1053.     typed_add_to_whois_queue(Type, nick, func, format, vlist);
  1054.     va_end(vlist);
  1055. #else
  1056.     typed_add_to_whois_queue(Type, nick, func, format, arg1, arg2,
  1057.         arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
  1058. #endif
  1059. }
  1060.  
  1061. void    add_ison_to_whois(nick, func)
  1062. void    (*func) ();
  1063. char    *nick;
  1064. {
  1065.     typed_add_to_whois_queue(WHOIS_ISON, nick, func, (char *) 0, (char *)0);
  1066. }
  1067.  
  1068. void    add_userhost_to_whois(nick, func)
  1069. char    *nick;
  1070. void    (*func)();
  1071. {
  1072.     typed_add_to_whois_queue(WHOIS_USERHOST, nick, func, (char *) 0, (char *)0);
  1073. }
  1074.  
  1075. #ifdef USE_STDARG_H
  1076. void    typed_add_to_whois_queue(int type, char *nick, void (*func)(), char *format, va_list vlist)
  1077. #else
  1078. void    typed_add_to_whois_queue(type, nick, func, format,
  1079.         arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
  1080. void    (*func) ();
  1081. char    *format,
  1082.     *nick;
  1083. int    type;
  1084. char    *arg1,
  1085.     *arg2,
  1086.     *arg3,
  1087.     *arg4,
  1088.     *arg5,
  1089.     *arg6,
  1090.     *arg7,
  1091.     *arg8,
  1092.     *arg9,
  1093.     *arg10;
  1094. #endif
  1095. {
  1096.     define_big_buffer(buffer);
  1097.     WhoisQueue *new;
  1098.  
  1099.     if ((nick == (char *) 0) || ! is_server_connected(from_server))
  1100.     {
  1101.         free_big_buffer(buffer);
  1102.         return;
  1103.     }
  1104.     if (index(nick, '*') == (char *) 0)
  1105.     {
  1106.         new = (WhoisQueue *) new_malloc(sizeof(WhoisQueue));
  1107.         new->text = (char *) 0;
  1108.         new->nick = (char *) 0;
  1109.         new->func = func;
  1110.         new->next = (WhoisQueue *) 0;
  1111.         new->type = type;
  1112.         if (format)
  1113.         {
  1114. #ifdef USE_STDARG_H
  1115.             vsprintf(buffer, format, vlist);
  1116. #else
  1117.             sprintf(buffer, format, arg1, arg2, arg3, arg4, arg5,
  1118.                 arg6, arg7, arg8, arg9, arg10);
  1119. #endif
  1120.             malloc_strcpy(&(new->text), buffer);
  1121.         }
  1122.         malloc_strcpy(&(new->nick), nick);
  1123.         if ((void *) get_server_qhead(from_server) == (void *) 0)
  1124.             set_server_qhead(from_server, new);
  1125.         if (get_server_qtail(from_server))
  1126.             ((WhoisQueue *) get_server_qtail(from_server))->next =
  1127.                 new;
  1128.         set_server_qtail(from_server, new);
  1129.         switch(type)
  1130.         {
  1131.         case WHOIS_ISON:
  1132. #ifdef MONITOR_Q
  1133.             put_it("+++ ISON %s", nick);
  1134. #endif
  1135.             send_to_server("ISON %s", nick);
  1136.             break;
  1137.         case WHOIS_USERHOST:
  1138. #ifdef MONITOR_Q
  1139.             put_it("+++ USERHOST %s", nick);
  1140. #endif
  1141.             send_to_server("USERHOST %s", nick);
  1142.             break;
  1143.         case WHOIS_WHOIS:
  1144. #ifdef MONITOR_Q
  1145.             put_it("+++ WHOIS %s", nick);
  1146. #endif
  1147.             send_to_server("WHOIS %s", nick);
  1148.             if (!get_server_whois(from_server))
  1149.                 send_to_server("WHOIS %s", whois_nick);
  1150.             break;
  1151.         }
  1152.     }
  1153.     free_big_buffer(buffer);
  1154. }
  1155.  
  1156. extern    void    userhost_cmd_returned(stuff, nick, text)
  1157. WhoisStuff    *stuff;
  1158. char     *nick;
  1159. char     *text;
  1160. {
  1161.     define_big_buffer(args);
  1162.  
  1163.     strcpy(args, stuff->nick ? stuff->nick : empty_string);
  1164.     strcat(args, stuff->oper ? " + " : " - ");
  1165.     strcat(args, stuff->away ? "+ " : "- ");
  1166.     strcat(args, stuff->user ? stuff->user : empty_string);
  1167.     strcat(args, " ");
  1168.     strcat(args, stuff->host ? stuff->host : empty_string);
  1169.     parse_line((char *) 0, text, args, 0, 0);
  1170.     free_big_buffer(args);
  1171. }
  1172.